amd iommu: Allow device deassignment.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 18 Feb 2008 09:33:40 +0000 (09:33 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 18 Feb 2008 09:33:40 +0000 (09:33 +0000)
Signed-off-by: Wei Wang <wei.wang2@amd.com>
xen/arch/x86/domctl.c
xen/arch/x86/hvm/iommu.c
xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c
xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
xen/include/asm-x86/iommu.h

index 3a37b809fde8dea5dacbdfda6a3ddb09b4f0a528..4e8ad4acdedcf442cfe2eeeb0817d9685deae45b 100644 (file)
@@ -601,7 +601,7 @@ long arch_do_domctl(
         if ( !device_assigned(bus, devfn) )
             break;
 
-        reassign_device_ownership(d, dom0, bus, devfn);
+        deassign_device(d, bus, devfn);
         gdprintk(XENLOG_INFO, "XEN_DOMCTL_deassign_device: bdf = %x:%x:%x\n",
             bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         put_domain(d);
index 30c92f42eae534f725f2a21847f1d68f649712ae..963ef5a0296bae5acef6a29b9853092309a568ed 100644 (file)
@@ -133,3 +133,13 @@ int iommu_unmap_page(struct domain *d, unsigned long gfn)
 
     return hd->platform_ops->unmap_page(d, gfn);
 }
+
+void deassign_device(struct domain *d, u8 bus, u8 devfn)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return;
+
+    return hd->platform_ops->reassign_device(d, dom0, bus, devfn);
+}
index 7caa276f7354b6294549063df9c5b214121aa8a8..815a1aee88cba2409b70227e61d259972b65f4d6 100644 (file)
@@ -562,10 +562,17 @@ void amd_iommu_domain_destroy(struct domain *d)
     release_domain_devices(d);
 }
 
+void amd_iommu_return_device(struct domain *s, struct domain *t, u8 bus, u8 devfn)
+{
+    pdev_flr(bus, devfn);
+    reassign_device(s, t, bus, devfn);
+}
+
 struct iommu_ops amd_iommu_ops = {
     .init = amd_iommu_domain_init,
     .assign_device  = amd_iommu_assign_device,
     .teardown = amd_iommu_domain_destroy,
     .map_page = amd_iommu_map_page,
     .unmap_page = amd_iommu_unmap_page,
+    .reassign_device = amd_iommu_return_device,
 };
index 79e2e493b6f287c6aef49ac8073ea3a1f1bd57d3..2eda71514e6c3bb44f6192345490c72f48b7d3b7 100644 (file)
@@ -2164,6 +2164,7 @@ struct iommu_ops intel_iommu_ops = {
     .teardown = iommu_domain_teardown,
     .map_page = intel_iommu_map_page,
     .unmap_page = intel_iommu_unmap_page,
+    .reassign_device = reassign_device_ownership,
 };
 
 /*
index 2cea432bbe6cf4cb1d46cdc232439c80e28c1884..1f975dfa539a2a8b14c2ac054448698205777e83 100644 (file)
@@ -74,6 +74,7 @@ int iommu_domain_init(struct domain *d);
 void iommu_domain_destroy(struct domain *d);
 int device_assigned(u8 bus, u8 devfn);
 int assign_device(struct domain *d, u8 bus, u8 devfn);
+void deassign_device(struct domain *d, u8 bus, u8 devfn);
 void reassign_device_ownership(struct domain *source,
                                struct domain *target,
                                u8 bus, u8 devfn);
@@ -102,6 +103,7 @@ struct iommu_ops {
     void (*teardown)(struct domain *d);
     int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn);
     int (*unmap_page)(struct domain *d, unsigned long gfn);
+    void (*reassign_device)(struct domain *s, struct domain *t, u8 bus, u8 devfn);
 };
 
 #endif /* _IOMMU_H_ */